package www.authority.config.online.filter;


import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import www.authority.config.online.OnlineSession;
import www.authority.config.online.dao.OnlineSessionDAO;
import www.authority.config.online.dao.ShiroConstants;
import www.authority.entity.SysUserEntity;
import www.authority.entity.SysUserOnlineEntity;
import www.authority.service.SysUserOnlineService;
import www.authority.util.ShiroUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;


/**
 * 自定义访问控制
 * 
 * @author
 */
public class OnlineSessionFilter extends AccessControlFilter
{
    /**
     * 强制退出后重定向的地址
     */
    @Value("${shiro.user.loginUrl}")
    private String loginUrl;

	/**
	 * 控制在线人数
	 */
	@Value("${shiro.session.maxUserNum}")
	private Integer maxUserNum;


    @Autowired
    private OnlineSessionDAO onlineSessionDAO;

	@Autowired
	private SysUserOnlineService sysUserOnlineService;

    /**
     * 表示是否允许访问；mappedValue就是[urls]配置中拦截器参数部分，如果允许访问返回true，否则false；
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
            throws Exception
    {   //如果访问登录
    	if(isLoginRequest(request, response)){
    		return true;
	    }
	    // 判断用户是否存在
        Subject subject = getSubject(request, response);
        if (subject == null || subject.getPrincipal() == null|| subject.getSession() == null)
        {
            return true;
        }

	    Session session = onlineSessionDAO.readSession(subject.getSession().getId());
        if (session != null && session instanceof OnlineSession)
        {
            OnlineSession onlineSession = (OnlineSession) session;
	        request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession);
            // 把user对象设置进去
            boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
            if (isGuest == true)
            {
                SysUserEntity user = ShiroUtils.getSubjectUser();
                if (user != null)
                {
                    onlineSession.setUserId(user.getUserId());
                    onlineSession.setLoginName(user.getLoginName());
                    onlineSession.setDeptName(user.getDept().getDeptName());
                    onlineSession.markAttributeChanged();
                }
            }

	        // 控制在线人数
	        Collection<Session> activeSessions = onlineSessionDAO.getActiveSessions();

	        if(activeSessions.size() >  maxUserNum){
		        // 在线人数多
		        onlineSession.setStatus(OnlineSession.OnlineStatus.maxUserNum_line);
		        sysUserOnlineService.delete(SysUserOnlineEntity.class,onlineSession.getId());
	        }

	        // 判断是否在线
	        if (onlineSession.getStatus() != OnlineSession.OnlineStatus.on_line)
	        {
		        SendWriter(onlineSession.getStatus(),request,response);
		        // 删除以前账号
		        onlineSessionDAO.delete(onlineSession);
		        return false;
	        }

	        for(Session activeSession :activeSessions){
		        //清除该用户以前登录时保存的session
		        //对比传入SessionId与缓存中SessionId是否一致，一致则判断为同一设备登陆，不做删除
		        // 之前的登录
		        if(activeSession !=null && activeSession instanceof OnlineSession) {
			        OnlineSession onlineSessionOld = (OnlineSession)activeSession;
			        if(!onlineSessionOld.getId().equals(onlineSession.getId()) && onlineSessionOld.getUserId().equals(onlineSession.getUserId())){
				        //异地登录
			        	onlineSessionOld.setStatus(OnlineSession.OnlineStatus.address_line);
				        sysUserOnlineService.delete(SysUserOnlineEntity.class,onlineSessionOld.getId());
			        }
		        }
	        }

        }
        return true;
    }

    /**
     * 表示当访问拒绝时是否已经处理了；如果返回true表示需要继续处理；如果返回false表示该拦截器实例已经处理了，将直接返回即可。
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
    {
        Subject subject = getSubject(request, response);
        if (subject != null)
        {
            subject.logout();
        }
        saveRequestAndRedirectToLogin(request, response);
        return true;
    }

    // 跳转到登录页
    @Override
    protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException
    {
       // WebUtils.issueRedirect(request, response, loginUrl);
    }

    /**
     * 验证是什么操作
     */
    private void SendWriter(OnlineSession.OnlineStatus stauts, ServletRequest request, ServletResponse response)throws IOException{
	    response.setContentType("text/html;charset=utf-8");
	    PrintWriter out = response.getWriter();
	    out.println("<script>");
    	switch (stauts){
    		//  在线
		    case on_line:
			    break;
		    //强退
		    case off_line:
			    out.println("alert('强制下线，请重新登录！');");
			    break;
		    // 异地登录
		    case address_line:
			    out.println("alert('账号在其他地方登录！');");
			    break;
		    // 在线人数已满
		    case maxUserNum_line:
			    out.println("alert('在线人数已满，请稍后登录！');");
			    break;
				default:
		}
	    out.println("window.location.href = \"/login\"");
	    out.println("</script>");
	    out.flush();
    }
}
